package com.lgy.ms.service.service.business;

import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import com.lgy.ms.api.business.IAppSysUserService;
import com.lgy.ms.core.bean.RequestParams;
import com.lgy.ms.core.bean.ResponseParams;
import com.lgy.ms.core.bean.SessionInfo;
import com.lgy.ms.core.constant.RespCode;
import com.lgy.ms.core.dto.SysUserDTO;
import com.lgy.ms.core.enums.CommonEnum;
import com.lgy.ms.core.exception.AppException;
import com.lgy.ms.core.exception.BusinessException;
import com.lgy.ms.core.utils.EncryptUtil;
import com.lgy.ms.core.utils.SysHelper;
import com.lgy.ms.service.cache.AppSessionCache;
import com.lgy.ms.service.cache.SessionInfoCache;
import com.lgy.ms.service.config.GlobalNames;
import com.lgy.ms.service.dao.SysUserDao;
import com.lgy.ms.service.service.base.AppBaseService;
import com.lgy.ms.service.service.base.AppRequestParam;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service(value = "appSysUserService")
public class AppSysUserServiceImpl extends AppBaseService implements IAppSysUserService {

    private Logger log = LoggerFactory.getLogger(getClass());

    @Resource
    private SysUserDao sysUserDao;
    @Resource
    private SessionInfoCache sessionInfoCache;
    @Resource
    private AppSessionCache appSessionCache;

    @Override
    public ResponseParams<Object> add(RequestParams requestParams) throws BusinessException {
        ResponseParams<Object> response = buildResponseParams(requestParams);
        try {
            SysUserDTO sysUserDTO = super.paramToObject(requestParams, SysUserDTO.class);
            SysUserDTO oldUser = sysUserDao.selectByPhone(sysUserDTO.getPhone());
            if (oldUser != null) {
                throw new BusinessException("新增管理员失败：该手机号已被注册");
            }
            oldUser = sysUserDao.selectByUserName(sysUserDTO.getUserName());
            if (oldUser != null) {
                throw new BusinessException("新增管理员失败：账号已存在");
            }
            sysUserDTO.setUserId(SysHelper.getUUID("SysUser_", 32));
            EncryptUtil.encryptPassword(sysUserDTO, sysUserDTO.getPassword());
            sysUserDTO.setCreateTime(new Date());
            sysUserDTO.setErrorTimes(0);
            sysUserDTO.setIsAdmin(CommonEnum.No.value);
            sysUserDTO.setStatus(CommonEnum.Enable.value);
            sysUserDao.insert(sysUserDTO);
            return finish(response);
        } catch (Exception e) {
            throw super.processException(e, e.getMessage());
        }
    }

    @Override
    public ResponseParams<Object> queryByPage(RequestParams requestParams) throws BusinessException {
        try {
            SysUserDTO sysUserDTO = super.paramToObject(requestParams, SysUserDTO.class);
            List<SysUserDTO> list = sysUserDao.queryByPage(sysUserDTO);
            ResponseParams<Object> response = super.getPage(requestParams, list);
            return finish(response);
        } catch (Exception e) {
            throw super.processException(e, e.getMessage());
        }
    }

    @Override
    public ResponseParams<Object> login(RequestParams requestParams) throws BusinessException {
        ResponseParams<Object> response = buildResponseParams(requestParams);
        try {
            SysUserDTO dto = super.paramToObject(requestParams, SysUserDTO.class);
//            String randomCode = (String) requestParams.getExtenalMap().get("randomCode");
//            if (StrUtil.isEmpty(dto.getRandomCode())) {
//                throw new AppException("验证码不能为空");
//            }
//            if (!dto.getRandomCode().equals(randomCode)) {
//                throw new AppException("验证码错误");
//            }
            SysUserDTO sysUser = sysUserDao.selectByUserName(dto.getUserName());
            if (sysUser == null) {
                throw new AppException("您输入的用户名密码错误");
            }
            if (!StrUtil.equals(sysUser.getStatus(), CommonEnum.Enable.value)) {
                throw new AppException("管理员登录失败：账号被禁用");
            }
            Date freezeTime = sysUser.getFreezeTime();
            long currentTimeMillis = System.currentTimeMillis();
            if (freezeTime != null && currentTimeMillis < freezeTime.getTime()) {
                int mins = (int) (freezeTime.getTime() - currentTimeMillis) / 1000 / 60;
                mins = mins <= 1 ? 1 : mins;
                throw new AppException("账号被冻结，请在" + mins + "分钟后重试");
            }
            String encryptPass = EncryptUtil.encodeToPasswordHex(sysUser, dto.getPassword());
            if (!encryptPass.equals(sysUser.getPassword())) {
                log.info("密码错误，执行更新操作");
                int errorTimes = sysUser.getErrorTimes();
                int errorChance = GlobalNames.login_errorChance;
                int freezeMin = GlobalNames.login_freezeMin;
                SysUserDTO sysUserDTO = new SysUserDTO();
                sysUserDTO.setUserId(sysUser.getUserId());
                if (errorTimes >= errorChance) {
                    errorTimes = 1;
                } else {
                    errorTimes++;
                }
                sysUserDTO.setErrorTimes(errorTimes);
                String msg;
                if (errorTimes >= errorChance) {
                    sysUserDTO.setFreezeTime(DateUtils.addMinutes(new Date(), freezeMin));
                    msg = "操作过于频繁，账号将被冻结" + freezeMin + "分钟";
                } else {
                    msg = "您输入的用户名密码错误，错误" + (errorChance - errorTimes) + "次后账号将被冻结";
                }
                sysUserDao.updateByPrimaryKeySelective(sysUserDTO);
                throw new AppException(msg);
            } else {
                SysUserDTO sysUserDTO = new SysUserDTO();
                sysUserDTO.setUserId(sysUser.getUserId());
                sysUserDTO.setErrorTimes(0);
                sysUserDao.updateByPrimaryKeySelective(sysUserDTO);

                String sessionId = "";
                SessionInfo sessionInfo = sessionInfoCache.getSessionInfo(sysUser.getUserId());
                if (sessionInfo == null) {
                    sessionInfo = new SessionInfo();
                    sessionInfo.setUserId(sysUser.getUserId());
                    if (CommonEnum.Yes.value.equals(sysUser.getIsAdmin())) {
                        sessionInfo.setSys(true);
                    }
                }
                sessionId = appSessionCache.initSession(sessionInfo);

                Map<String, Object> map = Maps.newHashMap();
                map.put("user", sysUser);
                map.put("sessionId", sessionId);
                response.setParam(map);
            }
            return finish(response);
        } catch (Exception e) {
            throw super.processException(e, e.getMessage());
        }
    }

    @Override
    public ResponseParams<Object> logout(RequestParams requestParams) throws BusinessException {
        ResponseParams<Object> response = buildResponseParams(requestParams);
        try {
            SessionInfo sessionInfo = AppRequestParam.getSessionInfo();
            if (sessionInfo != null) {
                sessionInfoCache.removeSessionInfo(sessionInfo.getUserId());
            }
            return finish(response, RespCode.SUCCESS_CODE, RespCode.SUCCESS_CODE_MS);
        } catch (Exception e) {
            throw super.processException(e, e.getMessage());
        }
    }

    @Override
    public ResponseParams<Object> modifyPwd(RequestParams requestParams) throws BusinessException {
        ResponseParams<Object> response = buildResponseParams(requestParams);
        try {
            SysUserDTO dto = super.paramToObject(requestParams, SysUserDTO.class);
            SessionInfo sessionInfo = AppRequestParam.getSessionInfo();
            if (sessionInfo == null) {
                throw new AppException(RespCode.ERR_SESSION_TIMEOUT, "用户未登录");
            }
            SysUserDTO sysUser = sysUserDao.selectByPrimaryKey(sessionInfo.getUserId());
            String encryptPass = EncryptUtil.encodeToPasswordHex(sysUser, dto.getPassword());
            if (!encryptPass.equals(sysUser.getPassword())) {
                throw new AppException("原密码错误");
            }
            EncryptUtil.encryptPassword(sysUser, dto.getNewPwd());
            boolean isSuccess = sysUserDao.updateByPrimaryKeySelective(sysUser) > 0;
            if (!isSuccess) {
                throw new AppException("修改密码失败");
            }
            return finish(response, RespCode.SUCCESS_CODE, RespCode.SUCCESS_CODE_MS);
        } catch (Exception e) {
            throw super.processException(e, e.getMessage());
        }
    }

}
